package challenges;

import game.Challenge;
import gfx.Glyphs;
import gfx.Shapes;

import javax.microedition.khronos.opengles.GL10;

import util.GameClock;
import util.GameVars;
import android.graphics.Color;
import android.graphics.PointF;

/** Week 1 **/
public class ChainMemory extends Challenge{
	private short[] sequenceArray;
	private boolean[] dirtyArray;
	private int[][] colorArray;
	private int xLoc, yLoc;
	private PointF drawPoint, scoreLoc = new PointF(5, 2.5f);

	private long timer;
	
	private float halfSquare = .45f;

	private short drawIterator, chooseIterator, crossIterator, borderIterator;
	private short next, currentSequence, squareCount, counter, pauseTime, drawCounter, touchCount, touched, score;
	
	private boolean roundReady;
	
	public ChainMemory(){
		colorArray = new int[10][6];
		dirtyArray = new boolean[60];
		sequenceArray = new short[60];
		drawPoint = new PointF();
		pauseTime = 250;
		
		reset();
	}
	
	public void draw(GL10 gl){
		gl.glClearColor(.5f, .5f, .5f, 1f);
		drawCross(gl);
		drawBorder(gl);

		for(drawIterator = touchCount; drawIterator < drawCounter; ++drawIterator){
			if(sequenceArray[drawIterator] == -1)
				break;
			xLoc = sequenceArray[drawIterator] % 10;
			yLoc = sequenceArray[drawIterator] / 10;
			drawPoint.set(xLoc + .5f, yLoc + .5f);
			Shapes.drawSquare(gl, drawPoint, halfSquare, Color.red(colorArray[xLoc][yLoc]) / 255f, Color.green(colorArray[xLoc][yLoc]) / 255f, Color.blue(colorArray[xLoc][yLoc]) / 255f, Color.alpha(colorArray[xLoc][yLoc]) / 255f);
		}
		super.draw(gl);
		
		if(isGameOver){
			gl.glColor4f(1, 1, 1, 1);
			Glyphs.drawString(gl, "Score: " + score, scoreLoc, GameVars.TEXT_ALIGNMENT_CENTER);
		}
		if(isWon){
			gl.glColor4f(1, 1, 1, 1);
			Glyphs.drawString(gl, "Masterful Memory!", scoreLoc, GameVars.TEXT_ALIGNMENT_CENTER);
		}
	}
	
	public void update(long time){ 
		if(reloading)
			reset();
		super.update(time);
		
		if(GameClock.getInstance().getCurrentTime() > timer + pauseTime){
			if(drawCounter < currentSequence){
				++drawCounter;
				timer = GameClock.getInstance().getCurrentTime();
			}
		}
		if(!roundReady && drawCounter == currentSequence)
			roundReady = true;
		
		if(touchCount == squareCount)
			nextRound();
	}
	
	public void drawBorder(GL10 gl){
		for(borderIterator = 0; borderIterator <= 6; ++borderIterator)
			Shapes.drawSquare(gl, 5, borderIterator, 6, .05f, 0, 0, 0, 1);
		for(borderIterator = 0; borderIterator <= 10; ++borderIterator)
			Shapes.drawSquare(gl, borderIterator, 3, .05f, 4, 0, 0, 0, 1);
	}
	
	public void drawCross(GL10 gl){ 
		for(crossIterator = 0; crossIterator < 6; ++crossIterator)
			Shapes.drawSquare(gl, 5, crossIterator + .5f, 6, .1f, .75f, .75f, .75f, 1);
		for(crossIterator = 0; crossIterator < 10; ++crossIterator)
			Shapes.drawSquare(gl, crossIterator + .5f, 3, .1f, 4, .75f, .75f, .75f, 1);
	}
	
	private void nextRound(){
		roundReady = false;
		chooseNext();
		touchCount = 0;
		drawCounter = 0;
		timer = GameClock.getInstance().getCurrentTime();
	}
	
	private void chooseNext(){
		if(squareCount == 60){
			isWon = true;
			return;
		}
		next = (short) (Math.random() * (colorArray.length * colorArray[0].length - squareCount));
		counter = 0;
		for(chooseIterator = 0; chooseIterator < dirtyArray.length;++chooseIterator){
			if(dirtyArray[chooseIterator] == true)
				;
			else if(counter == next){
				dirtyArray[chooseIterator] = true;
				sequenceArray[currentSequence] = chooseIterator;
				++currentSequence;
				++squareCount;
				break;
			}
			else if(dirtyArray[chooseIterator] == false)
				++counter;
		}
	}
	
	private short checkBounds(PointF loc){
		return (short) ((short) loc.x + (short) (loc.y) * 10);
	}
	
	public boolean handleUp(PointF location) {
		if(super.handleUp(location))
			return false;
		if(checkBounds(location) == touched){
			if(touched == sequenceArray[touchCount]){
				++score;
				++touchCount;
			}
			else isGameOver = true;
		}
		touched = -1;
		return true;
	}

	public boolean handleDrag(PointF location) {
		if(super.handleDrag(location))
			return false;
		return true;
	}

	public boolean handleTouch(PointF location) {
		if(super.handleTouch(location))
			return false;
		if(roundReady)
			touched = checkBounds(location);
		return true;
	}
	
	private void reset(){
		for(short x = 0; x < colorArray.length * colorArray[0].length; ++x){
			colorArray[x % 10][x / 10] = Color.argb(255,(int) (Math.random() * 255), (int) (Math.random() * 255), (int) (Math.random() * 255));
		}
		for(short x = 0; x < dirtyArray.length; ++x)
			dirtyArray[x] = false;
		for(short x = 0; x < sequenceArray.length; ++x)
			sequenceArray[x] = -1;
		
		drawCounter = 0;
		timer = GameClock.getInstance().getCurrentTime();
		roundReady = false;
		
		currentSequence = 0;
		squareCount = 0;
		touchCount = 0;
		score = 0;

		for(int i = 0; i < 4; ++i)
			chooseNext();
	}
}